package com.yn.pet.controller.pc.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yn.common.exception.ServiceException;
import com.yn.common.utils.StringUtils;
import com.yn.common.utils.bean.BeanUtils;
import com.yn.common.utils.poi.ExcelUtil;
import com.yn.pet.bus.entity.DeviceSim;
import com.yn.pet.controller.pc.request.DeviceSimRequest;
import com.yn.pet.controller.pc.response.DeviceSimResponse;
import com.yn.pet.bus.entity.DeviceInfo;
import com.yn.pet.service.DeviceInfoService;
import com.yn.pet.service.DeviceSimService;
import io.jsonwebtoken.lang.Assert;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class DeviceSimBizService {

    private final DeviceInfoService deviceInfoService;
    private final DeviceSimService deviceSimService;

    public IPage<DeviceSimResponse> pageList(DeviceSimRequest request) {
        int currentPage = 1;
        int pageSize = 10;
        if (request.getCurrentPage() != null) {
            currentPage = request.getCurrentPage();
        }
        if (request.getPageSize() != null) {
            pageSize = request.getPageSize();
        }
        Set<Long> deviceIdSetFromName = new HashSet<>();
        String deviceName = request.getDeviceName();
        if (StringUtils.isNotBlank(deviceName)) {
            List<DeviceInfo> deviceInfos = deviceInfoService.listLikeDeviceName(deviceName);
            if (deviceInfos != null && !deviceInfos.isEmpty()) {
                deviceIdSetFromName = deviceInfos.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());
            }
        }

        Set<Long> deviceIdSetFromImei = new HashSet<>();
        String imei = request.getImei();
        if (StringUtils.isNotBlank(imei)) {
            List<DeviceInfo> deviceInfos = deviceInfoService.listLikeImei(imei);
            if (deviceInfos != null && !deviceInfos.isEmpty()) {
                deviceIdSetFromImei = deviceInfos.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());
            }
        }

        LambdaQueryWrapper<DeviceSim> wrapper = new LambdaQueryWrapper<DeviceSim>()
                .in(!CollectionUtils.isEmpty(deviceIdSetFromName), DeviceSim::getDeviceId, deviceIdSetFromName)
                .eq(!Objects.isNull(request.getDeviceId()), DeviceSim::getDeviceId, request.getDeviceId())
                .in(!CollectionUtils.isEmpty(deviceIdSetFromImei), DeviceSim::getDeviceId, deviceIdSetFromImei)
                .like(StringUtils.isNotBlank(request.getIccid()), DeviceSim::getIccid, request.getIccid())
                .like(StringUtils.isNotBlank(request.getPhoneNumber()), DeviceSim::getPhoneNumber, request.getPhoneNumber())
                .like(StringUtils.isNotBlank(request.getCarrier()), DeviceSim::getCarrier, request.getCarrier())
                .like(StringUtils.isNotBlank(request.getDataPlan()), DeviceSim::getDataPlan, request.getDataPlan())
                .ge(!Objects.isNull(request.getActivateTimeStart()), DeviceSim::getActivateTime, request.getActivateTimeStart())
                .le(!Objects.isNull(request.getActivateTimeEnd()), DeviceSim::getActivateTime, request.getActivateTimeEnd())
                .ge(!Objects.isNull(request.getExpireTimeStart()), DeviceSim::getExpireTime, request.getExpireTimeStart())
                .le(!Objects.isNull(request.getExpireTimeEnd()), DeviceSim::getExpireTime, request.getExpireTimeEnd())
                .eq(DeviceSim::getDataStatus, 1);
        Page<DeviceSim> page = deviceSimService.page(new Page<>(currentPage, pageSize), wrapper);
        return page.convert(deviceSim -> {
            DeviceSimResponse deviceSimResponse = new DeviceSimResponse();
            BeanUtils.copyBeanProp(deviceSimResponse, deviceSim);

            if (deviceSim.getDeviceId() != null) {
                DeviceInfo deviceInfo = deviceInfoService.getById(deviceSim.getDeviceId());
                if (deviceInfo != null) {
                    deviceSimResponse.setDeviceName(deviceInfo.getDeviceName());
                    deviceSimResponse.setImei(deviceInfo.getImei());
                }
            }
            return deviceSimResponse;
        });
    }

    public void saveDeviceSim(DeviceSim deviceSim) {
        String iccid = deviceSim.getIccid();
        Assert.hasText(iccid, "ICCID号不能为空");
        DeviceSim existDeviceSim = deviceSimService.getByIccid(iccid);
        if (existDeviceSim != null && existDeviceSim.getSimId() != null && !existDeviceSim.getSimId().equals(deviceSim.getSimId())) {
            throw new RuntimeException("ICCID号已存在");
        }
        Long deviceId = deviceSim.getDeviceId();
        if (deviceId != null) {
            DeviceInfo deviceInfo = deviceInfoService.getById(deviceId);
            if (deviceInfo == null) {
                throw new RuntimeException("设备不存在");
            }
            if (deviceInfo.getDataStatus() == 0) {
                throw new RuntimeException("设备不存在");
            }
            existDeviceSim = deviceSimService.getByDeviceId(deviceId);
            if (existDeviceSim != null && existDeviceSim.getSimId() != null && !existDeviceSim.getSimId().equals(deviceSim.getSimId())) {
                throw new RuntimeException("设备已绑定SIM卡");
            }
        }
        if (deviceSim.getSimId() == null) {
            deviceSim.setCreateTime(new Date());
//            deviceSim.setCreateBy(SecurityUtils.getUsername());
        }
        deviceSim.setUpdateTime(new Date());
//        deviceSim.setUpdateBy(SecurityUtils.getUsername());
        deviceSimService.saveOrUpdate(deviceSim);
    }

    public void bindDeviceSim(Long deviceId, Long simId) {
        Assert.notNull(deviceId, "设备ID不能为空");
        Assert.notNull(simId, "SIM卡ID不能为空");
        DeviceInfo deviceInfo = deviceInfoService.getById(deviceId);
        if (deviceInfo == null) {
            throw new RuntimeException("设备不存在");
        }
        if (deviceInfo.getDataStatus() == 0) {
            throw new RuntimeException("设备不存在");
        }
        DeviceSim existDeviceSim = deviceSimService.getByDeviceId(deviceId);
        if (existDeviceSim != null && existDeviceSim.getSimId() != null && !existDeviceSim.getSimId().equals(simId)) {
            throw new RuntimeException("设备已绑定SIM卡");
        }
        DeviceSim deviceSim = deviceSimService.getById(simId);
        if (deviceSim == null) {
            throw new RuntimeException("SIM卡不存在");
        }
        if (deviceSim.getDataStatus() == 0) {
            throw new RuntimeException("SIM卡不存在");
        }
        if (deviceSim.getDeviceId() != null) {
            throw new RuntimeException("SIM卡已绑定设备");
        }
        deviceSim.setDeviceId(deviceId);
        deviceSim.setUpdateTime(new Date());
//        deviceSim.setUpdateBy(SecurityUtils.getUsername());
        deviceSimService.updateById(deviceSim);
    }

    public void unBindDeviceSim(Long simId) {
        Assert.notNull(simId, "SIM卡ID不能为空");
        DeviceSim deviceSim = deviceSimService.getById(simId);
        if (deviceSim == null) {
            throw new RuntimeException("SIM卡不存在");
        }
        if (deviceSim.getDataStatus() == 0) {
            throw new RuntimeException("SIM卡不存在");
        }
//        deviceSim.setDeviceId(null);
//        deviceSim.setUpdateTime(new Date());
////        deviceSim.setUpdateBy(SecurityUtils.getUsername());
//        deviceSimService.updateById(deviceSim);
        LambdaUpdateWrapper<DeviceSim> deviceSimLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        deviceSimLambdaUpdateWrapper.set(DeviceSim::getDeviceId, null).eq(DeviceSim::getSimId, simId);
        deviceSimService.update(deviceSimLambdaUpdateWrapper);
    }

    public void removeDeviceSim(Set<Long> simIdSet) {
        Assert.notEmpty(simIdSet, "SIM卡ID不能为空");
        deviceSimService.removeByIds(simIdSet);
    }

    public String importDeviceSim(MultipartFile file) throws IOException {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        ExcelUtil<DeviceSimRequest> deviceSimExcelUtil = new ExcelUtil<>(DeviceSimRequest.class);
        List<DeviceSimRequest> deviceSimRequestList = deviceSimExcelUtil.importExcel(file.getInputStream());
        if (deviceSimRequestList.isEmpty()) {
            throw new RuntimeException("导入数据不能为空");
        }
        Set<String> iccidSet = deviceSimRequestList.stream().map(DeviceSimRequest::getIccid).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(iccidSet)) {
            throw new RuntimeException("导入数据不能为空");
        }
        Map<String, Long> deviceIdMap = new HashMap<>();
        Set<String> imeiSet = deviceSimRequestList.stream().map(DeviceSimRequest::getImei).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(imeiSet)) {
            deviceIdMap = deviceInfoService.listByImei(imeiSet).stream().collect(Collectors.toMap(DeviceInfo::getImei, DeviceInfo::getDeviceId, (key1, key2) -> key1));
        }
        for (DeviceSimRequest deviceSimRequest : deviceSimRequestList) {
            DeviceSim deviceSim = new DeviceSim();
            BeanUtils.copyBeanProp(deviceSim, deviceSimRequest);
            deviceSim.setDeviceId(deviceIdMap.get(deviceSimRequest.getImei()));
            try {
                this.saveDeviceSim(deviceSim);
                successNum++;
                successMsg.append("<br/>").append(successNum).append("iccid ").append(deviceSim.getIccid()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("iccid ").append(deviceSim.getIccid()).append(" 导入失败:").append(e.getMessage());
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();

    }
}
